import os
import sys
import re
import webbrowser
import open_trace_in_ui

JSON_FORMATER = "{\"name\":\"%s\", \"cat\":\"%s\", \"ph\":\"%s\", \"ts\":%d, \"tid\":%d, \"dur\":%d, \"args\":%s}"
ARGS_FORMATER = "{\"tag\":\"%s\", \"rts\":%d, \"text\":\"%s\"}"

################################################# data structure ################################################
global_ts = 1
class log_line:
    def __init__(self, line_text):
        self.text = line_text.strip()
    def get_pid(self):
        ret = self.text.split()
        if len(ret) >= 3:
            return int(ret[2])
        return -1024
    def get_tid(self):
        ret = self.text.split()
        if len(ret) >= 4:
            return int(ret[3])
        return -1025
    def get_ts(self):
        global global_ts
        global_ts += 1
        return global_ts
    def get_rts(self):
        return 0
    def match(self, log_event):
        return re.search(log_event.exp, self.text) != None

class log_event:
    def __init__(self, name, exp, cat="INFO", ph="B"):
        self.name = name
        self.exp = exp
        self.cat = cat
        self.ph = ph

LOG_EVENTS_INFO = [
    # OpenSession
    log_event("OpenSession开始", "trans server opensession", "INFO", "X"),
    log_event("选路开始", "add tran request to pending \[lane=", "INFO", "X"),
    log_event("等待选路结果", "add lane\[.+\] to pending and start waiting", "INFO", "X"),
    log_event("选路结果返回", "receive lane cond laneId\[.+\]", "INFO", "X"),
    log_event("选路成功", "trans server opensession", "INFO", "X"),
    log_event("OpenSession同步阶段成功", "sever TransOpenChannel ok", "INFO", "X"),
]

LOG_EVENTS_ERROR = [
    log_event("选路失败", "trans on lane\[.+\] request failed", "ERROR", "X"),
    log_event("OpenSession同步阶段失败", "server TransOpenChannel err", "ERROR", "X"),
    log_event("认证通道打开失败", "OnAuthConnOpenFailed: reqId=.+, reason=.+", "ERROR", "X"),
]

LOG_EVENTS = LOG_EVENTS_ERROR + LOG_EVENTS_INFO

class trace_event:
    def __init__(self, name="UNKOWN", cat="DEFAULT", ph="B", ts=0, rts=0, pid=1024, tid=1025, dur=1, text=""):
        self.name = name
        self.cat = cat
        self.ph = ph
        self.ts = ts
        self.rts = rts
        self.pid = pid
        self.tid = tid
        self.dur = dur
        self.text = text
        self.tag = "UNKOWN"

    def to_args(self):
        return ARGS_FORMATER % (self.tag, self.rts, self.text)

    def to_line(self):
        return JSON_FORMATER % (self.name, self.cat, self.ph, self.ts, self.pid, self.tid, self.dur, self.to_args())

def match_line(log_line, log_event):
    if log_line.match(log_event):
        return trace_event(log_event.name, log_event.cat, log_event.ph, log_line.get_ts(), log_line.get_rts(), log_line.get_pid(), log_line.get_tid(), 1, log_line.text)
    return None

def check_file_format(filepath):
    filename = os.path.basename(filename)
    return True

def get_json_path(filepath):
    json_dir = os.path.dirname(os.path.abspath(__file__))
    jsonpath = json_dir + "\\" + "tmp.json"
    return jsonpath

glabal_cnt = 0
def do_process_line_stub(line):
    global global_cnt
    global_cnt += 1
    if global_cnt == 1:
        return trace_event("打开Session", "测试", "X", 0, 0, 1024, 1025, 1, "raw log line test ...")
    elif global_cnt == 2:
        return trace_event("关闭Session", "测试", "X", 0, 0, 1024, 1025, 1, "raw log line test ...")
    else:
        return ""
    return ""

def do_process_line(line):
    global LOG_EVENTS
    log_line = log_line(line)
    for log_event in LOG_EVENTS:
        trace_event = match_line(log_line, log_event)
        if trace_event != None:
            return trace_event.to_line()
    return ""

def make_json_str(json_lines):
    if len(json_lines) <= 0:
        return "[]"
    json_str = "[\n"
    for line in json_lines[:-1]:
        json_str += "\t" + line + ",\n"
    json_str += "\t" + json_lines[-1] + "\n"
    return json_str + "]"

def do_process_file(filepath, jsonpath):
    file = open(filepath, encoding='utf-8', errors='ignore')
    json = open(jsonpath, 'w', encoding='utf-8')
    jsonlines = []
    for line in file.readlines():
        #print(line)
        jsonline = do_process_line(line) # can use do_process_line_stub for test
        if jsonline == ""
            continue
        jsonlines.append(jsonline)
    for line in jsonlines:
        print(line)
    jsonstr = make_json_str(jsonlines)
    print(jsonstr)
    json.write(jsonstr)
    json.close()

def process_log_file(filepath):
    print("process log file:%s" % filepath
    jsonpath = get_json_path(filepath)
    print("jsonpath = %s" % jsonpath)
    do_process_file(filepath, jsonpath)
    return jsonpath

if __name__ == '__main__':
    print("Hello Easy Trace!")
    argc = len(sys.argv)
    print("argc = %d" % argc)
    for i in range(1, argc):
        print("arg[%d] = %s" % (i, sys.argv[i]))
    if argc >= 2:
        logpath = sys.argv[1]
        if check_file_format(logpath):
            jsonpath = process_log_file(logpath)
            open_trace_in_ui.open(jsonpath)
